package logic

import (
	"context"
	"encoding/json"
	"fmt"
	"time"

	"mall/common/globalkey"
	// "mall/common/resultx"
	"mall/common/subscribex"
	"mall/service/backend/common/utils/pointy"
	"mall/service/mqueue/common/types"
	"mall/service/mqueue/job/internal/svc"
	"mall/service/user/rpc/userclient"

	"github.com/hibiken/asynq"
	// "github.com/pkg/errors"
	"github.com/silenceper/wechat/v2/miniprogram/subscribe"
	"github.com/zeromicro/go-zero/core/logx"
	"github.com/zeromicro/go-zero/core/service"
)

// var ErrPaySuccessNotifyUserFailed = resultx.NewErrCode(resultx.PAYMENT_NOTIFY_USER_FAILED)

type PaySuccessNotifyUserProcessor struct {
	svcCtx *svc.ServiceContext
}

func NewPaySuccessNotifyUserProcessor(svcCtx *svc.ServiceContext) *PaySuccessNotifyUserProcessor {
	return &PaySuccessNotifyUserProcessor{
		svcCtx: svcCtx,
	}
}

func (l *PaySuccessNotifyUserProcessor) ProcessTask(ctx context.Context, t *asynq.Task) error {
	var p types.PaySuccessNotifyUserPayload
	if err := json.Unmarshal(t.Payload(), &p); err != nil {
		// return errors.Wrapf(ErrPaySuccessNotifyUserFailed, "PaySuccessNotifyUserProcessor payload err: %v, payLoad: %+v", err, t.Payload())
		return fmt.Errorf("PaySuccessNotifyUserProcessor payload json.Unmarshal failed: %v: %w", err, asynq.SkipRetry)
	}

	// 1、get user openid
	res, err := l.svcCtx.UserRpc.GetUserAuthByUserId(ctx, &userclient.GetUserAuthByUserIdReq{
		PlatformId: pointy.GetPointer(globalkey.ThirdPartyPlatformWechatMini),
		UserId:     pointy.GetPointer(uint64(p.UserId)),
	})
	if err != nil {
		// return errors.Wrapf(ErrPaySuccessNotifyUserFailed, "pay success notify user fail, rpc get user err: %v, orderSn: %s, userId: %d", err, p.OrderSn, p.UserId)
		return fmt.Errorf("PaySuccessNotifyUserProcessor user not found: %v: %w", err, asynq.SkipRetry)
	}

	if res.Openid == nil {
		return fmt.Errorf("PaySuccessNotifyUserProcessor user not found: %w", asynq.SkipRetry)
	}

	// 2、send notify
	msgs := l.getMessages(p.OrderSn, *res.Openid)
	for _, msg := range msgs  {
		l.SendNotificationWxMini(ctx, msg)
	}

	return nil
}

// get send data
func (l *PaySuccessNotifyUserProcessor) getMessages(orderSn string, openId string) []*subscribe.Message {
	return []*subscribe.Message{
		{
			ToUser:     openId,
			TemplateID: subscribex.ForumOrderShipmentTemplateID,
			Data:       map[string]*subscribe.DataItem{
				"character_string12": {Value: "快递单号"}, // 快递单号
				"thing11": {Value: " "}, // 快递公司
				"time8": {Value: " "}, // 时间
				"character_string9": {Value: orderSn}, // 订单号
				"thing7": {Value: " "}, // 商品
			},
		},
	}
}

// SendNotificationWxMini send to wechat mini
func (l *PaySuccessNotifyUserProcessor) SendNotificationWxMini(ctx context.Context, msg *subscribe.Message) {
	if l.svcCtx.Config.Mode != service.ProMode {
		msg.MiniprogramState = "developer"
	} else {
		msg.MiniprogramState = "formal"
	}

	var maxRetryNum int64 = 5
	var retryNum int64
	// Prevent user slowdown, delays, retries
	for {
		time.Sleep(time.Duration(1) * time.Second)

		err := l.svcCtx.MiniProgram.GetSubscribe().Send(msg)
		if err != nil {
			if retryNum > maxRetryNum {
				logx.WithContext(ctx).Errorf("Payment successful send wechat mini subscription message failed retryNum: %d, err: %v, msg: %+v", retryNum, err, msg)
				return
			}

			retryNum++
			continue
		}

		return
	}
}
